package com.elric.mall.common.utils;

import com.elric.mall.common.exception.ApiException;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author 作者[Yuxuan.he]
 * @version 1.0.00  2021-09-16 10:44
 */
public class ObjectCreateUtil {
    
    /**
     * 获取对象的属性值
     * @param object
     * @param fieldName
     * @return
     */
    public static Object getValueForField(Object object,String fieldName){
        Object value=null;
        try {
            if(object==null||StringUtils.isEmpty(fieldName)){
                return value;
            }
            Field[] declaredFields = object.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                // 设置属性是可以访问的
                field.setAccessible( true );
                if(fieldName.equals(field.getName())){
                    //得到此属性的值
                    value=field.get(object);
                    break;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new ApiException("反射获取属性值异常!");
        }
        return value;
    }

    /**
     * 反射对象的属性设置值
     * @param bean
     * @param fieldName
     * @param value
     * @throws Exception
     */
    public static void setFieldValue(Object bean, String fieldName, String value)throws Exception {
        if(!StringUtils.isEmpty(fieldName)){
            Class<?> clazz = bean.getClass();
            List<Field> fieldList = new ArrayList<>();
            fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
            // 如果继承了父类，则查找父类相关字段（只找一层）
            if (clazz.getSuperclass() != null) {
                fieldList.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
            }
            for (Field field : fieldList) {
                if(fieldName.equals(field.getName())){
                    String setMethodName = "set" + fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1);
                    Method method = clazz.getMethod(setMethodName, field.getType());
                    invoke(bean,method,field,value);
                }
            }
        }
    }

    /**
     * 反射对象的属性设置值
     * @param bean
     * @param fieldName
     * @param value
     * @throws Exception
     */
    public static void setFieldValue(Object bean, String fieldName, Object value)throws Exception {
        if(!StringUtils.isEmpty(fieldName)){
            Class<?> clazz = bean.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if(fieldName.equals(field.getName())){
                    String setMethodName = "set" + fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1);
                    Method method = clazz.getMethod(setMethodName, field.getType());
                    method.invoke(bean, value);
                }
            }
        }
    }


    /**
     * 反射设值
     * @param bean
     * @param method
     * @param field
     * @param value
     */
    public static void invoke(Object bean,Method method,Field field,String value){
        try {
            if (!StringUtils.isEmpty(value)) {
                String fieldType = field.getType().getSimpleName();
                if ("String".equals(fieldType)) {
                    method.invoke(bean, value);
                } else if ("Date".equals(fieldType)) {
                    Date temp = DateUtils.getDateForString(value);
                    method.invoke(bean, temp);
                } else if ("Integer".equals(fieldType)
                        || "int".equals(fieldType)) {
                    Integer intval = Integer.parseInt(value);
                    method.invoke(bean, intval);
                } else if ("Long".equalsIgnoreCase(fieldType)) {
                    Long temp = Long.parseLong(value);
                    method.invoke(bean, temp);
                } else if ("Double".equalsIgnoreCase(fieldType)) {
                    Double temp = Double.parseDouble(value);
                    method.invoke(bean, temp);
                } else if ("Boolean".equalsIgnoreCase(fieldType)) {
                    Boolean temp = Boolean.parseBoolean(value);
                    method.invoke(bean, temp);
                } else if ("BigDecimal".equalsIgnoreCase(fieldType)) {
                    BigDecimal temp = new BigDecimal(value);
                    method.invoke(bean, temp);
                } else {
                    throw new ApiException("反射不支持此类型:"+ fieldType);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new ApiException("反射设置值异常,字段名称为【"+field.getName()+"】字段类型为【"+field.getType().getSimpleName()+"】字段值为【"+value+"】");
        }
    }

    /**
     * 判断对象中是否有某个属性
     * @param object
     * @param fieldName
     * @return
     */
    public static boolean checkField(Object object,String fieldName){
        boolean flag=false;
        if(object==null){
            return flag;
        }
        Field[] fields=object.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if(fields[i].getName().equals(fieldName)){
                flag=true;
                break;
            }
        }
        return flag;
    }

    /**
     * 将类中的类型为 String 的属性值中的,空格去掉
     * @param model
     * @throws Exception
     */
    public static void trimBean(Object model) throws Exception {
        Class clazz = model.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String fieldType = field.getType().getSimpleName();
            String fieldName=field.getName();
            if ("String".equals(fieldType)) {
                // 设置属性是可以访问的
                field.setAccessible( true );
               //得到此属性的值
                Object  value=field.get(model);
                String setMethodName = "set" + fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1);
                Method method = clazz.getMethod(setMethodName, field.getType());
                if(value!=null){
                    if(fieldName.equals("name")||fieldName.equals("code")){
                        invoke(model,method,field,value.toString() .replaceAll("\\s*", ""));
                    }else {
                        invoke(model,method,field,value.toString().trim());
                    }
                }
            }
        }
    }

}
